class TaskWorker extends Worker{
    constructor(notifyAvailable,...wrokerArgs){
        super(...wrokerArgs);
        //初始化为不可用状态
        this.available=false;
        this.resolve=null;
        this.reject=null;

        this.notifyAvailable=notifyAvailable;
        this.onmessage=()=>this.setAvailable();
    }
    dispatch({resolve,reject,postMessageArgs}){
        this.available=false;
        this.onmessage=({data})=>{
            resolve(data);
            this.setAvailable();
        }
        this.onerror=(e)=>{
            reject(e);
            this.setAvailable();
        };
        this.postMessage(...postMessageArgs);
    }

    setAvailable(){
        this.available=true;
        this.resolve=null;
        this.reject=null;
        this.notifyAvailable()
    }
}


class WorkerPool{
    constructor(poolSize,...wrokerArgs){
        this.taskQueue=[];
        this.workers=[];
        for(let i=0;i<poolSize;++i){
            this.workers.push(
                new TaskWorker(()=>this.dispatchIfAvailable(),...wrokerArgs)
            );
        }
    }
    enqueue(...postMessageArgs){
        return new Promise((resolve,reject)=>{
            this.taskQueue.push({resolve,reject,postMessageArgs});
            this.dispatchIfAvailable();
        });
    }
    dispatchIfAvailable(){
        if(!this.taskQueue.length){
            return;
        }
        for(const worker of this.workers){
            if(worker.available){
                let a=this.taskQueue.shift();
                worker.dispatch(a);
                break;
            }
        }
    }
    close(){
        for(const worker of this.workers){
            worker.terminate();
        }
    }
}

const totalFloats=1E8;
const numTasks=20;
const floatsPerTask=totalFloats / numTasks;

const numWorkers=4;

const pool=new WorkerPool(numTasks,'./worker.js');
let arrayBuffer=new SharedArrayBuffer(4*totalFloats);
let view=new Float32Array(arrayBuffer);
for(let i=0;i<totalFloats;++i){
    view[i]=Math.random();
}

let partialSumPromises=[];
for(let i=0;i<totalFloats;i+=floatsPerTask){
    partialSumPromises.push(
        pool.enqueue({
            startIdx:i,
            endIdx:i+floatsPerTask,
            arrayBuffer:arrayBuffer
        })
    );
}

Promise.all(partialSumPromises).then((partialSums)=>partialSums.reduce((x,y)=>x+y))
.then(console.log);

